<template>
	<div class="chatAppBody">
		<div class="chatTitle">{{entInfo.companyName}}</div>
		<div class="chatBox">
			<div class="chatNotice" v-if="historyList.moreMessageBtn"><a class="moreMessageBtn" @click="getHistoryList">点击加载更多记录</a></div>
			<div v-for="row in msgList">
				<div v-if="row.isme!=true">
					<div class="chatNotice">{{row.time}}</div>
					<div class="chatRow">
						<el-avatar class="chatAvatar" :size="30" :src="row.avator"></el-avatar>
						<div class="chatMsgContent">
							<div class="chatUsername">{{row.name}}</div>
							<div class="chatContent" v-html="row.content"></div>
						</div>
					</div>
				</div>
				<div v-if="row.isme==true">
					<div class="chatNotice" v-if="row.show_time==true">{{row.time}}</div>
					<div class="chatRow chatRowMe">
						<div class="chatContent" v-html="row.content"></div>
					</div>
				</div>
			</div>
		</div>
		<div class="chatNotice" v-if="websocket.serverReturnClose"><a class="alink" @click="window.location.reload()">点击重新建立会话</a></div>
		<div class="chatBottom" v-show="!websocket.serverReturnClose">
			<div class="chatSendProduct" v-if="visitorProduct!=null">
				<img :src="visitorProduct.img" class="productImg"/>
				<div class="productInfo">
					<div>{{visitorProduct.title}}</div>
					<div class="productPrice">{{visitorProduct.price}}</div>
				</div>
				<div class="productBtns">
					<div class="el-icon-close" @click="visitorProduct=null"></div>
					<el-button size="mini" type="primary" @click="sendProductInfo">发送</el-button>
				</div>
			</div>
			<div class="hotQuestions" v-if="question.hotQuestion.length!=0">
				<a class="slideInRightItem"  v-for="row in question.hotQuestion" @click="visitor.message=row;chatToUser($event)">{{row}}</a>
			</div>
			<div class="chatAreaBox">
				<div class="chatArea">
					<textarea class="chatAreaInput" v-model="visitor.message"  @keyup.ctrl.enter.exact="chatToUser($event)" @keyup.enter.exact="chatToUser($event,'enter')" ></textarea>
					<div @click="showExtendTool==true?showExtendTool=false:showExtendTool=true;" class="chatJiahaoBtn iconfont icon-jiahao"></div>
					<div @click="chatToUser($event)" class="chatSendBtn iconfont icon-fasong"></div>
				</div>
				<div class="chatExtend" v-show="showExtendTool">
					<div class="iconExtendBtn" >
						<div class="elIcon el-icon-picture"></div>
						<div>图片</div>
					</div>
					<div class="iconExtendBtn" >
						<div  class="elIcon el-icon-upload"></div>
						<div>文件</div>
					</div>
					<div class="iconExtendBtn" @click="callKefu('phone')">
						<div class="elIcon el-icon-phone-outline" style="font-size: 22px;"></div>
						<div>语音</div>
					</div>
					<div class="iconExtendBtn" @click="callKefu('video')">
						<div class="elIcon el-icon-video-camera" style="font-size: 22px;"></div>
						<div>视频</div>
					</div>
				</div>
			</div>

			<div class="chatCopyright">
				<i class="el-icon-chat-dot-round"></i> Powered by {{entInfo.companyName}}
			</div>
		</div>
		<div class="coverMask" v-show="peerjs.remoteVideoStream">
			<video id="remoteVideo" controls autoplay></video>
		</div>
		<div class="coverMask" v-show="peerjs.remoteAudioStream">
			<audio id="remoteAudio" controls autoplay></audio>
		</div>
		
		<audio id="chatMessageAudio" style="display: none;" :src="require('@/assets/alert2.ogg')"></audio>
	</div>
</template>

<script>
	import tools from '../tools/functions.js'
	import storage from '../tools/localStorage.js'
	import xss from 'xss'
	import "../tools/peer.js"
	export default {
	  name: 'ChatApp',
		data() {
		  return {
			  window:window,
			  visitor:{
				  to_id:"",
				  visitor_id:"",
				  ent_id:"",
				  message:"",
			  },
			  peerjs:{
				  peer:null,
				  peerjsId:"",
				  localStream:null,
				  remoteAudioStream:null,
				  remoteVideoStream:null,
				  kefuPeerId:"",
				  call:null,
			  },
			  question:{
				  hotQuestion:[],
			  },
			  historyList:{
				  list:[],
				  moreMessageBtn:false,
				  page:1
			  },
			  msgList:[],
			  entInfo:{
				  companyName:"",
			  },
			  visitorProduct:null,
			  websocket:{
				  // 设置重连时间间隔（单位：毫秒）
				  RECONNECT_INTERVAL: 1000,
				  // 设置最大重连次数
				  MAX_RECONNECT_TIMES:30,
				  //重连次数
				  RECONNET_TIMES :0,
				  //ws对象
				  instance:null,
				  //服务端返回close指令
				  serverReturnClose:false,
			  },
			  showExtendTool:false,

		  }
		},
		methods: {
			visitorLogin(){
				var _this=this;
				let entId=tools.getQuery("ent_id");
				let toId=tools.getQuery("to_id");
				let visitorId=storage.getFakeCookie("visitor_"+entId);
				this.visitor.ent_id=entId;
				this.$axios.post(this.ApiHost+'/2/visitorLogin', {
					ent_id:entId,
					to_id:toId,
					visitor_id:visitorId,
				}).then(function (response) {
					var code=response.data.code;
					var msg=response.data.msg;
					if(code!=200){
						_this.$message({
						  message: msg,
						  type: 'error'
						});
						_this.loading = _this.$loading({
							lock: true,
							text: msg,
							background: 'rgba(0, 0, 0, 0.7)'
						});
						return ;
					}
					let result=response.data.result;
					_this.visitor.to_id=result.to_id;
					_this.visitor.visitor_id=result.visitor_id;
					if(!visitorId){
						storage.setFakeCookie("visitor_"+_this.visitor.ent_id,_this.visitor.visitor_id,response.data.visitorCookie);
					}
					//连接websocket
					_this.connect();
					//自动欢迎
					_this.getAutoWelcome();
					//展示历史消息
					_this.getHistoryList();
					//获取热门问题
					_this.getTopRequest();
					//获取扩展信息
					_this.getUrlExtra();
				}).catch(function (error) {
					_this.$message({
					  message: error.message,
					  type: 'error'
					});
				});
			},
			//获取常问关键词
			getTopRequest(){
				var _this=this;
				let entId=tools.getQuery("ent_id");
				this.$axios.get(this.ApiHost+'/2/getTopQuestion?ent_id='+entId).then(function (response) {
					let result=response.data.result;
					if(result.hotQuestion){
						let hotQuestion=result.hotQuestion.replace("，",",").split(",");
						_this.question.hotQuestion=hotQuestion;
					}

					console.log(hotQuestion);
				}).catch(function (error) {
				});
			},
			//展示自动欢迎信息
			getAutoWelcome(){
				var _this=this;
				let entId=tools.getQuery("ent_id");
				this.$axios.get(this.ApiHost+'/2/notices?ent_id='+entId).then(function (response) {
					let result=response.data.result;
					let welcome=result.welcome;
					let companyName=result.username;
					_this.entInfo.companyName=companyName;
					tools.displayGreetings(welcome,function(row){
						let message={
							isme:false,
							name:row.name,
							avator:row.avator,
							content:row.content,
							time:tools.shortTime(tools.getNowDate())
						}
						tools.alertSound("chatMessageAudio");
						_this.msgList.push(message);
						_this.scrollBottom();
					});
					
				}).catch(function (error) {
				});
			},
			//展示历史消息记录
			getHistoryList(){
				var _this=this;
				let pagesize=5;
				this.$axios.get(this.ApiHost+'/2/messages_page',{params:{
					pagesize:5,
					ent_id:this.visitor.ent_id,
					page:this.historyList.page,
					visitor_id:this.visitor.visitor_id,
				}}).then(function (response) {
					let result=response.data.result;
					let msgList=result.list;
					if(msgList.length>=pagesize){
						_this.historyList.moreMessageBtn=true;
					}else{
						_this.historyList.moreMessageBtn=false;
					}
					for(var i=0;i<msgList.length;i++) {
						let row = msgList[i];
						if (row["mes_type"] == "kefu") {
							row.isme = false;
						} else {
							row.isme = true;
						}
						row.content=tools.replaceSpecialTag(row.content);
						row.time = tools.shortTime(row["time"]);
						row.show_time=true;
						_this.msgList.unshift(row);
					}
					_this.historyList.page++;
				}).catch(function (error) {
				});
			},
		   //发送给客户
			chatToUser:function(e) {
				let _this=this;
				//用户点击了ctrl+enter触发
				if(e && e.ctrlKey && e.keyCode==13) { 
					this.visitor.message += '\n';
					return;
				}
				let message=xss(tools.trim(this.visitor.message.replace(/\r\n|\n/g,"<br>"),"<br>"));
				if(message=="") return;
				let sendMessage = {
					content:message,
					from_id: this.visitor.visitor_id,
					to_id:this.visitor.to_id,
				};
				let showMessage={
					isme:true,
					content:tools.replaceSpecialTag(message),
					show_time:false,
				}
				this.msgList.push(showMessage);
				this.scrollBottom();
				this.visitor.message="";
				
				this.$axios.post(this.ApiHost+'/2/message',sendMessage).then(function (response) {

				}).catch(function (error) {
					_this.$message({
					  message: error.message,
					  type: 'error'
					});
				});
			},
			//处理收到消息
			receiveMessage(msg){
				let content = {
					avator :msg.avator,
					name:msg.name,
					content:tools.replaceSpecialTag(msg.content),
					isme:false,
					time:tools.shortTime(msg.time)
				}
				//声音通知
				tools.alertSound("chatMessageAudio");
				//桌面通知
				tools.notify(msg.name, {
					body: msg.content,
					icon: msg.avator
				},function(notification) {
					window.focus();
					notification.close();
				});
				//标题闪动
				tools.flashTitle(document.title);
				this.msgList.push(content);
				this.scrollBottom();
			},
			//滚动到底部
			scrollBottom:function(){
				var _this=this;
				this.$nextTick(function(){
					var container = _this.$el.querySelector(".chatBox");
					container.scrollTop = 999999999;
				});
			},
			/**
			 * 连接websocket
			 */
			connect () {
				var _this=this;
				let ws = new WebSocket(this.WebsocketHost+`/ws_visitor?visitor_id=${this.visitor.visitor_id}&to_id=${this.visitor.to_id}`);
				ws.onopen = function () {
					console.log('WebSocket 连接已打开');
					//_this.reconnectTimes = 0;
				};
				ws.onerror = function () {
					console.log('WebSocket 连接错误');
					// 尝试重连
					_this.reconnect();
				};
				ws.onclose = function () {
					console.log('WebSocket 连接已关闭');
					// 尝试重连
					_this.reconnect();
				};
				ws.onmessage = function (event) {
					console.log(`收到服务器的消息：${event.data}`);
					let result=event.data;
					let serverMessage=JSON.parse(result);
					let type=serverMessage.type;
					let data=serverMessage.data;
					if(type=="message"){
						_this.receiveMessage(data);
					}
					if(type=="close"||type=="force_close"){
						_this.websocket.serverReturnClose=true;
						_this.websocket.instance.close();
					}
					//客服接受通话
					if(type=="accept"){
						_this.peerjs.kefuPeerId=data;
						//访客调用客服
						_this.callPeer();
					}
					if (type == "refuse") {
						_this.$message({
							message: "客服已挂断",
							type: 'error'
						});
						_this.callClear();
					}
				};
				_this.websocket.instance=ws;
			},
			// 尝试重连
			reconnect(){
				var _this=this;
				if (_this.websocket.serverReturnClose) {
					console.log('停止重连,服务端close指令');
					return;
				}
				if (_this.websocket.RECONNET_TIMES >= _this.websocket.MAX_RECONNECT_TIMES) {
					console.log('重连失败');
					return;
				}
				_this.websocket.RECONNET_TIMES++;
				console.log(`正在尝试重连（第 ${_this.websocket.RECONNET_TIMES} 次）`);
				setTimeout(function () {
					_this.connect();
				}, _this.websocket.RECONNECT_INTERVAL); 
			},
			//获取url中的扩展信息
			getUrlExtra(){
				let extra=tools.getQuery("extra");console.log(extra);
				if(!extra) return;
				let jsonStr=tools.b64DecodeUnicode(extra);
				let extraJson=JSON.parse(jsonStr);
				this.visitorProduct=extraJson.visitorProduct;
			},
			//发送产品信息
			sendProductInfo(){
				if(this.visitorProduct==null) return;
				this.visitor.message="product["+JSON.stringify(this.visitorProduct)+"]";
				this.chatToUser();
				this.visitorProduct=null;
			},
			//语音请求
			callKefu(type){
				var isVideo=false;
				if(type=="video"){
					isVideo=true;
				}
				var _this=this;
				let res=tools.getCompatibleUserMedia({video:isVideo, audio: {
					noiseSuppression: true,
					echoCancellation: true,
				}},function(stream) {
					_this.initPeerjs(function(peerid){
						//初始化成功
						_this.peerjs.peerjsId=peerid;
						_this.peerjs.localStream=stream;
						//请求客服发送他们的peerid过来
						_this.$axios.post(_this.ApiHost+'/2/callKefu',{"action":"callpeer",kefu_id:_this.visitor.to_id,visitor_id:_this.visitor.visitor_id});
						_this.$message({
							type: 'success',
							message: "请求通话指令已经发出！"
						});
					});
				},function(err) {
					_this.$message({
						type: 'error',
						message: err
					});
                });
				if(!res){
					_this.$message({
						type: 'error',
						message: "Your browser does not support the getUserMedia API."
					});
				}
			},
			//初始化peer
			initPeerjs(callback){
				let peer = new Peer();
				this.peerjs.peer=peer;
				var _this=this;
				peer.on('open', function(id) {
					console.log('My peer ID is: ' + id);
					callback(id);
				});
				peer.on('close', function() {
					console.log('My peer close');
				});
				peer.on('disconnected', function() {
					console.log('My peer disconnected');
				});
				peer.on('error', function() {
					console.log('My peer error');
				});
			},
			//call peer
			callPeer(){
				var _this=this;
				//调用请求远程客服
				let call = _this.peerjs.peer.call(_this.peerjs.kefuPeerId, _this.peerjs.localStream);
				call.on('stream', function(remoteStream) {
					console.log("call stream",remoteStream);
					var videoTracks = remoteStream.getVideoTracks();
					var audioTracks = remoteStream.getAudioTracks();
					//视频流
					if (videoTracks.length > 0) {
						console.log("客服视频接待");
						var remoteVideo = document.getElementById("remoteVideo");
						remoteVideo.srcObject = remoteStream;
						remoteVideo.play();
						_this.peerjs.remoteVideoStream=remoteStream;
					}else if (audioTracks.length > 0) {
						//音频流
						console.log("客服音频接待");
						var remoteAudio = document.getElementById("remoteAudio");
						remoteAudio.srcObject = remoteStream;
						remoteAudio.play();
						_this.peerjs.remoteAudioStream=remoteStream;
					}
				});
				call.on('close', function() {
					console.log("call close");
				});
				call.on('error', function(err) {
					console.log("call error",err);
				});
				this.peerjs.call=call;
			},
			//清理call
			callClear(){
				var _this=this;
				if(_this.peerjs.call){
					_this.peerjs.call.close();
					_this.peerjs.call=null;
				} 
				if(_this.peerjs.remoteVideoStream){
					var tracks=_this.peerjs.remoteVideoStream.getTracks();
					for(var i=0;i<tracks.length;i++){
						tracks[i].stop();
					}
					_this.peerjs.remoteVideoStream=null;
				}
				if(_this.peerjs.remoteAudioStream){
					var tracks=_this.peerjs.remoteAudioStream.getTracks();
					for(var i=0;i<tracks.length;i++){
						tracks[i].stop();
					}
					_this.peerjs.remoteAudioStream=null;
				}
				if(_this.peerjs.localStream){
					var tracks=_this.peerjs.localStream.getTracks();
					for(var i=0;i<tracks.length;i++){
						tracks[i].stop();
					}
					_this.peerjs.localStream=null;
				}
			},
		},
		mounted: function () {
			this.visitorLogin();
		}
	}
</script>

<style lang="scss">
	.chatAppBody{
		display: flex;
		flex-direction: column;
		height: 100vh;
		background-color: #f1f5f8;
	}
	.chatTitle{
		background: #fff;
		padding: 5px 0px;
		text-align: center;
		font-size: 14px;
	}
	.chatBox{
		flex: 1;
		padding: 0px 5px;
		padding-bottom: 15px;
		overflow: auto;
	}
	.chatBottom{
		display: flex;
		flex-direction: column;
	}
	.chatRow{
		display: flex;
		align-items: flex-end;
		margin: 5px 0px;
	}
	.chatAvatar{
		margin-right: 5px;
		flex-shrink: 0;
	}
	.chatUsername {
	    font-size: 12px;
	    white-space: nowrap;
	    color: #999;
	    margin-bottom: 2px;
	}
	.chatContent{
		border-radius: 10px 10px 10px 0px;
		padding: 10px;
		background-color: rgb(255,255,255);
		box-shadow: 0 5px 30px rgb(50 50 93 / 8%), 0 1px 3px rgb(0 0 0 / 5%);
		font-size: 14px;
		word-break: break-all;
		line-height: 21px;
		display: inline-block;
	}
	.productCard{
		cursor: pointer;
		background: #fff;
		padding: 5px;
		border-radius: 2px;
		width: auto;
		max-width: 730px;
		display: flex;
		border-radius: 5px;
	}
	.productCard img{
		width: 100px;
		height: 100px;
		margin-right: 15px;
	}
	.productCard .productCardPrice{
		color: #ff7736;
		font-weight: bold;
		font-size: 16px;
		margin-top: 10px;
	}
	.productCard .productCardTitle{
		color: #333;
	}
	.chatRowMe{
		justify-content: flex-end;
	}
	.chatRowMe .chatContent{
		border-radius: 10px 10px 0px 10px;
	}
	.chatNotice{
		text-align: center;
		color: #bbb;
		margin: 8px 0;
		font-size: 12px;
	}
	.chatAreaBox{
		margin: 0px 10px;
		margin-bottom: 10px;
		box-shadow: 0 5px 30px rgb(50 50 93 / 8%), 0 1px 3px rgb(0 0 0 / 5%);
		border-radius: 10px;
	}
	.chatArea{
		display: flex;
		padding: 3px 5px;
		align-items: center;
		background: #fff;
		border-radius: 10px;
	}
	.chatArea .iconfont{
		color: #383838;
		font-size: 18px;
		margin: 0px 6px;
		cursor: pointer;
	}
	.chatArea .iconfont:hover{
		color: #409eff;
	}
	.chatAreaInput{
		border-radius: 10px;
		border: 0;
		flex: 1;
		outline: none;
		resize: none;
		box-sizing: border-box;
		color: #505050;
		min-height: 50px;
		font-size: 16px;
	}
	.chatCopyright{
		color: #999a9b;
		font-size: 12px;
		text-align: center;
		margin-bottom: 10px;
		filter: grayscale(1);
		opacity: .9;
		font-family: Inter,-apple-system,system-ui,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Tahoma,Arial,sans-serif;
	}
	.chatExtend{
		border-radius: 0px 0px 10px 10px;
		background: #f1f5f8;
		padding: 10px;
		min-height: 200px;
		margin-top: -5px;
	}
	.chatExtend .iconExtendBtn{
		width: 60px;
		background: #fff;
		display: flex;
		height: 60px;
		text-align: center;
		float: left;
		color: #9fa19f;
		flex-direction: column;
		justify-content: center;
		align-items: center;
		font-size: 12px;
		margin: 0px 10px 10px 0px;
		border-radius: 10px;
	}
	.chatExtend .iconExtendBtn .elIcon{
		font-size:26px;
		color: #767676;
	}
	.hotQuestions{
		margin-bottom: 5px;
		width: 100%;
		white-space: nowrap;
		overflow-x: auto;
	}
	.hotQuestions a{
		    display: inline-block;
		    margin-left: 10px;
		    border-radius: 20px;
		    cursor: pointer;
		    font-size: 12px;
		    padding: 5px 9px;
		    background: #fff;
		    border: 1px solid #dcdfe6;
		    color: #606266;
	}
	.chatContent a{
		color: #07a9fe;
		text-decoration: none;
	}
	.moreMessageBtn{
		display: inline-block;
		word-break: break-all;
		color: #07a9fe;
		margin: 0 24px;
		max-width: calc(100% - 48px);
		background-color: #fff;
		border-radius: 16px;
		font-size: 12px;
		padding: 4px 16px;
		cursor: pointer;
	}
	.alink{
		display: inline-block;
		word-break: break-all;
		color: #07a9fe;
		font-size: 12px;
		cursor: pointer;
	}
	.chatSendProduct{
		display: flex;
		background: #fff;
		margin: 2px 10px;
		padding: 10px;
		font-size: 14px;
		border-radius: 10px;
		position: absolute;
		bottom: 85px;
		left: 0;
		right: 0;
		z-index: 999;
		box-shadow: 0 5px 30px rgb(50 50 93 / 8%), 0 1px 3px rgb(0 0 0 / 5%);
	}
	.chatSendProduct .productImg{
		max-width: 80px;
		max-height: 80px;
	}
	.chatSendProduct .productInfo{
		margin: 0 5px;
		flex: 1;
	}
	.chatSendProduct .productPrice{
		color: #ff5000;
		margin-top: 10px;
	}
	.chatSendProduct .productBtns{
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: space-around;
	}
	.chatSendProduct .el-icon-close{
		font-size: 18px;
		cursor: pointer;
	}
	.coverMask{
		position: fixed;
		width: 100%;
		height: 100%;
		background: #fff;
	}
	.coverMask #remoteVideo{
		width: 100%;
		height: 100%;
	}
	.coverMask #remoteAudio{
		width: 100%;
	}
	</style>